﻿
//常量字符串转化类
namespace n_ConstString
{
using System;
using n_ET;
using n_ParseNet;
using n_UnitList;
using n_VarList;
using n_VarNode;
using n_VarType;
using n_WordList;
using n_Parse;

//常量表达式处理类
public static class ConstExpression
{
	//计算常量表达式
	public static string GetExpressionValue( int ConstIndex, string UnitName )
	{
		return 表达式( ConstIndex, UnitName );
	}
	
	//根据类型计算一个数字常量的底层数值,超出范围则返回 null
	public static string GetRealValue( string Number, string Type )
	{
		if( Number == null ) {
			return null;
		}
		long N = long.Parse( Number );
		switch( Type ) {
			case VarType.BaseType.Bool:
				if( N > 1 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Bit:
				if( N > 1 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Uint8:
				if( N < 0 || N > 255 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Uint16:
				if( N < 0 || N > 65535 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Uint24:
				if( N < 0 || N > 16777215 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Uint32:
				if( N < 0 || N > 4294967295 ) {
					return null;
				}
				return N.ToString();
			case VarType.BaseType.Sint8:
				if( N < -128 || N > 127 ) {
					return null;
				}
				if( N < 0 ) {
					return (256 + N).ToString();
				}
				else {
					return N.ToString();
				}
			case VarType.BaseType.Sint16:
				if( N < -32768 || N > 32767 ) {
					return null;
				}
				if( N < 0 ) {
					return (65536 + N).ToString();
				}
				else {
					return N.ToString();
				}
			case VarType.BaseType.Sint24:
				if( N < -8388608 || N > 8388607 ) {
					return null;
				}
				if( N < 0 ) {
					return (16777216 + N).ToString();
				}
				else {
					return N.ToString();
				}
			case VarType.BaseType.Sint32:
			case VarType.BaseType.fix:
				if( N < -2147483648 || N > 2147483647 ) {
					return null;
				}
				if( N < 0 ) {
					return (4294967296 + N).ToString();
				}
				else {
					return N.ToString();
				}
				
			default: return null;
		}
	}
	
	static string 表达式( int Index, string UnitName )
	{
		string Result = null;
		string Head = ParseNet.NodeSet[ Index ][ 0 ];
		switch( Head ) {
			case ParseNet.Node.表达式:		Result = 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 1 ] ), UnitName ); break;
			case ParseNet.Node.括号运算:		Result = 括号运算( Index, UnitName ); break;
			case ParseNet.Node.双目运算符:	Result = 双目运算( Index, UnitName ); break;
			case ParseNet.Node.单目运算:		Result = 单目运算( Index, UnitName ); break;
			case ParseNet.Node.常量数组分量:	Result = 常量数组分量( Index, UnitName ); break;
			case ParseNet.Node.变量:			Result = 变量( Index, UnitName ); break;
			case ParseNet.Node.终结词:		Result = 终结词( Index, UnitName ); break;
			case ParseNet.Node.函数地址:		Result = 函数地址( Index, UnitName ); break;
			default :
				ET.WriteParseError( Index, "<常量表达式> 未定义的运算项: " + Head );
				ET.ShowError( "<常量表达式> 未定义的运算项: " + Head );
				break;
		}
		return Result;
	}
	
	static string 括号运算( int Index, string UnitName )
	{
		return 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 2 ] ), UnitName );
	}
	
	static string 双目运算( int Index, string UnitName )
	{
		//获取运算符号
		int OperIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		string Oper = WordList.GetWord( OperIndex );
		
		//解析左右两个操作数
		string Value1 = 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 1 ] ), UnitName );
		string Value2 = 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 3 ] ), UnitName );
		if( Value1 == null || Value2 == null ) {
			return null;
		}
		long D1 = long.Parse( Value1 );
		long D2 = long.Parse( Value2 );
		long D = 0;
		switch( Oper ) {
			case "+": D = D1 + D2; break;
			case "-": D = D1 - D2; break;
			case "*": D = D1 * D2; break;
			case "/": D = D1 / D2; break;
			default:	ET.WriteParseError( OperIndex, "常量表达式中不支持此运算: " + Oper ); break;
		}
		return D.ToString();
	}
	
	static string 单目运算( int Index, string UnitName )
	{
		//获取运算符号
		int OperIndex = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		string Oper = WordList.GetWord( OperIndex );
		
		//解析左右两个操作数
		string Value1 = 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 2 ] ), UnitName );
		if( Value1 == null ) {
			return null;
		}
		long D1 = long.Parse( Value1 );
		long D = 0;
		switch( Oper ) {
			case "-": D = -D1; break;
			default:	ET.WriteParseError( OperIndex, "常量表达式中不支持此运算: " + Oper ); break;
		}
		return D.ToString();
	}
	
	static string 常量数组分量( int Index, string UnitName )
	{
		//循环解析常量数组分量
		int AIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		int Length = ParseNet.NodeSet[ AIndex ].Length / 2;
		long[] List = new long[ Length ];
		
		for( int i = 1; i < ParseNet.NodeSet[ AIndex ].Length; i += 2 ) {
			//解析数组下标
			string d = 表达式( int.Parse( ParseNet.NodeSet[ AIndex ][ i ] ), UnitName );
			List[(i-1)/2] = long.Parse( d );
		}
		//解析数组下标
		string Value1 = 表达式( int.Parse( ParseNet.NodeSet[ Index ][ 5 ] ), UnitName );
		if( Value1 == null ) {
			return null;
		}
		long D1 = long.Parse( Value1 );
		if( D1 >= Length ) {
			ET.WriteParseError( int.Parse( ParseNet.NodeSet[ Index ][ 4 ] ), "常量数据的下标应小于分量数目: " + D1 + " >= " + Length );
			return null;
		}
		return List[ D1 ].ToString();
	}
	
	static string 变量( int Index, string BaseUnitName )
	{
		int AIndex = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		int FirstIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		int NextIndex = int.Parse( ParseNet.NodeSet[ Index ][ 3 ] );
		string[] Cut = ParseNet.NodeSet[ NextIndex ];
		int CurrentIndex = 1;
		
		//迭代处理元件嵌套引用
		string NextUnitName = null;
		string FirstNameWord = WordList.GetWord( FirstIndex );
		if( AIndex != -1 ) {
			NextUnitName = VarType.Root + "." + FirstNameWord;
		}
		else {
			NextUnitName = BaseUnitName + "." + FirstNameWord;
		}
		if( UnitList.GetIndex( NextUnitName ) == -1 ) {
			return 终结词( FirstIndex, BaseUnitName );
		}
		//迭代处理成员引用
		string UnitName = NextUnitName;
		for( CurrentIndex = 1; CurrentIndex < Cut.Length; ++CurrentIndex ) {
			int ParseIndex = int.Parse( Cut[ CurrentIndex ] );
			if( ParseNet.NodeSet[ ParseIndex ][ 0 ] != ParseNet.Node.点运算 ||
			   ParseNet.NodeSet[ ParseIndex ][ 3 ] != "-1" ) {
				ET.WriteParseError( FirstIndex, "<常量> 元件类型名只能进行点运算" );
				return null;
			}
			string Name = WordList.GetWord( int.Parse( ParseNet.NodeSet[ ParseIndex ][ 2 ] ) );
			NextUnitName += "." + Name;
			if( UnitList.GetIndex( NextUnitName ) == -1 ) {
				break;
			}
			UnitName = NextUnitName;
		}
		if( Cut.Length <= CurrentIndex ) {
			ET.WriteParseError( FirstIndex, "<常量> 变量名和元件名相同,引用错误" );
			return null;
		}
		int VarIndex = int.Parse( Cut[ CurrentIndex ] );
		VarIndex = int.Parse( ParseNet.NodeSet[ VarIndex ][ 2 ] );
		return 终结词( VarIndex, UnitName );
	}
	
	static string 终结词( int Index, string UnitName )
	{
		string Name = WordList.GetWord( Index );
		
		//判断字符常量或数字
		if( ConstString.isValue( Name ) ) {
			string Type = null;
			string Number = ConstString.GetValue( ref Type, Name, Index );
			if( Type == null ) {
				return null;
			}
			return Number;
		}
		//判断是否为静态变量
		int j = VarList.GetStaticIndex( UnitName + "." + Name );
		if( j == -1 ) {
			ET.WriteParseError( Index, "未定义的常量: " + UnitName + "." + Name );
			return null;
		}
		VarNode n = VarList.Get( j );
		if( !n.isConst || n.Value.StartsWith( "I " ) ) {
			return null;
		}
		return n.Value;
	}
	
	static string 函数地址( int Index, string UnitName )
	{
		int AIndex = int.Parse( ParseNet.NodeSet[ Index ][ 2 ] );
		
		int ErrorIndex = -1;
		string Name = null;
		Parse.GetMemberNames( UnitName, AIndex, ref Name, ref ErrorIndex );
		
		//判断字符常量或数字
		if( ConstString.isValue( Name ) ) {
			ET.WriteParseError( ErrorIndex, "数组成员常量用#addr只能获取静态变量的地址: " + Name );
			return null;
		}
		
		//这里可能是扫描常量的时候还没有记录静态变量的缘故
		//判断是否为静态变量
		//int j = VarList.GetStaticIndex( Name );
		//if( j == -1 ) {
		//	ET.WriteParseError( ErrorIndex, "扫描数组常量时遇到未定义的静态变量: " + Name );
		//	return null;
		//}
		
		int AT_Index = int.Parse( ParseNet.NodeSet[ Index ][ 1 ] );
		string AType = WordList.GetWord( AT_Index );
		
		if( AType != "#addr" ) {
			return AType + "+" + Name;
		}
		else {
			return "#" + Name;
		}
	}
}
//字符串编码转换类
public static class StringCoder
{
	//计算一组字符串的编码
	public static string GetCode( string Strings, ref int Length, ref int CodeType, int Index )
	{
		if( Strings.EndsWith( "(unicode)" ) ) {
			CodeType = 2;
			return GetCharCode( Strings.Remove( Strings.Length - 9 ), ref Length, Index, CodeType );
		}
		//if( Strings.EndsWith( ")" ) ) {
		//	CodeType = 1;
		//	return GetLatticeCode( Strings, ref Length, Index );
		//}
		CodeType = 0;
		return GetCharCode( Strings, ref Length, Index, CodeType );
	}
	
	/*
	//计算一组字符串的点阵编码
	static string GetLatticeCode( string Strings, ref int Length, int Index )
	{
		string Mes = "文字点阵正确格式(其中BIUS为粗体,斜体,下划线,中划线可选项): \"ABCD\"(宋体, 12, BIUS)";
		try {
		Strings = Strings.Remove( Strings.Length - 1 ).Remove( 0, 1 );
		int SPL = Strings.LastIndexOf( '(' );
		if( SPL == -1 ) {
			ET.WriteParseError( Index, Mes );
			return null;
		}
		string Text = Strings.Remove( SPL - 1 );
		string FontText = Strings.Remove( 0, SPL + 1 );
		bool[][] LB = LatticeToCode.GetLatticeFormTextFont( Text, FontText, true, 0, 0 );
		string Result = LatticeToCode.GetCode( LB, LatticeToCode.L_RightDown );
		
		string Head = Result.Remove( Result.IndexOf( '\n' ) );
		string[] cut = Head.Split( ',' );
		int Width = int.Parse( cut[ 0 ] );
		int AreaN = int.Parse( cut[ 1 ] );
		Length = 2 + Width * AreaN;
		
		Result = Result.Replace( "\n", "" ).TrimEnd( ',' );
		return Result;
		}
		catch {
			ET.WriteParseError( Index, Mes );
			return null;
		}
	}
	*/
	
	//计算一组字符串的编码
	static string GetCharCode( string Strings, ref int Length, int Index, int CodeType )
	{
		Length = 0;
		string Result = "";
		
		int st = 1;
		if( Strings[0] == '@' ) {
			if( Strings[1] != '"' ) {
				ET.WriteParseError( Index, "字符串需要以双引号开始: " + Strings );
			}
			st = 2;
		}
		
		//迭代处理字符
		for( int i = st; i < Strings.Length - 1; ++i ) {
			char c = Strings[ i ];
			
			if( st == 1 && c == '\\' ) {
				++i;
				c = Strings[ i ];
				if( i == Strings.Length ) {
					ET.WriteParseError( Index, "转义字符格式不对: " + Strings );
				}
				else {
					switch( c ) {
						case '0': 	Result += "0,"; break;
						case 'r': 	Result += "13,"; break;			//0x0D
						case 'n': 	Result += "10,"; break;			//0x0A
						case 't': 	Result += "11,"; break;
						case 'z': 	Result += "26,"; break;			//0x1A
						case '\\':	Result += (int)c + ","; break;	// \
						case '"':	Result += (int)c + ","; break;	// "
						default:  ET.WriteParseError( Index, "<字符串> 不支持的转义字符: " + c ); break;
					}
				}
				Length += 1;
			}
			else {
				int CODE = (int)c;
				if( CodeType == 0 && CODE > 255 ) {
					byte[] gbk = System.Text.Encoding.GetEncoding("GBK").GetBytes( c.ToString() );
					Result += gbk[0] + ",";
					Result += gbk[1] + ",";
					Length += 2;
				}
				else {
					Result += CODE + ",";
					Length += 1;
				}
			}
		}
		Result += "0";
		Length += 1;
		return Result;
	}
}
//常量字符串类
public static class ConstString
{
	//用到此处数值的地方参考程序备忘
	public static float FixScale = 1024f;
	public static int NFixScale = 1024;
	
	
	//计算一个常量的值和类型,其中类型包括两种,分别是作为有符号数和无符号数时的类型,格式: T1,T2
	//支持的格式:
	// true false high low 0x?? 0b?? 34 'A'
	public static string GetValue( ref string Type, string Const, int Index )
	{
		ErrorIndex = Index;
		
		if( Const == "true" ) {
			Type = VarType.BaseType.Bool;
			return "1";
		}
		if( Const == "false" ) {
			Type = VarType.BaseType.Bool;
			return "0";
		}
		
		//注意下边还有一段代码,  isValue() 也相关
		
//		if( Const == "HIGH" ) {
//			Type = VarType.BaseType.Bit;
//			return "1";
//		}
//		if( Const == "LOW" ) {
//			Type = VarType.BaseType.Bit;
//			return "0";
//		}
		long Number = 0;
		
		
		bool isInt32 = false;
		if( Const.EndsWith( "s" ) ) {
			Const = Const.Remove( Const.Length - 1 );
			isInt32 = true;
		}
		
		
		//转换字符值
		if( Const.StartsWith( "'" ) && Const.EndsWith( "'" ) ) {
			Number = SwitchChar( Const );
		}
		//转换十六进制数值
		else if( Const.StartsWith( "0x" ) || Const.StartsWith( "0X" ) ) {
			Number = SwitchHex( Const );
		}
		//转换二进制数值
		else if( Const.StartsWith( "0b" ) || Const.StartsWith( "0B" ) ) {
			Number = SwitchBin( Const );
		}
		//转换十进制数值
		else {
			bool Fix = false;
			Number = SwitchDec( Const, ref Fix );
			if( Fix ) {
				Type = VarType.BaseType.fix;
				return Number.ToString();
			}
		}
		string Type1 = VarType.BaseType.Uint + GetUnsignedWidth( Number );
		string Type2 = VarType.BaseType.Sint + GetSignedWidth( Number );
		Type = Type1 + "," + Type2;
		
		if( Number == 0 || Number == 1 ) {
			Type += "," + VarType.BaseType.Bit;
		}
		
		if( isInt32 ) {
			Type = VarType.BaseType.Uint32 + "," + VarType.BaseType.Sint32;
		}
		
		return Number.ToString();
	}
	
	//判断一个字符串是否为常量
	public static bool isValue( string Const )
	{
		if( ( Const[ 0 ] >= '0' && Const[ 0 ] <= '9' ) || Const.StartsWith( "'" ) ) {
			return true;
		}
		if( Const == "true" || Const == "false" ) {//|| Const == "HIGH" || Const == "LOW" ) {
			return true;
		}
		return false;
	}
	
	//计算一个常量的值和类型
	static long SwitchChar( string Const )
	{
		Const = Const.Substring( 1, Const.Length - 2 );
		if( Const == @"\r" ) {
			return 13;
		}
		if( Const == @"\n" ) {
			return 10;
		}
		if( Const == @"\t" ) {
			return 11;
		}
		if( Const == @"\\" ) {
			return (int)'\\';
		}
		if( Const.Length != 1 ) {
			ET.WriteParseError( ErrorIndex, "字符常量的有效字符数只能是1个: " + Const );
			return 0;
		}
		long l = (long)Const[ 0 ];
		if( l >= 128 ) {
			byte[] gbk = System.Text.Encoding.GetEncoding("GBK").GetBytes( Const );
			l = gbk[1] * 256 + gbk[0];
		}
		return l;
	}
	
	//转换十六进制常量
	static long SwitchHex( string Const )
	{
		Const = String.Join( "", Const.Split( '_' ) );
		if( Const.Length != 4 && Const.Length != 6 && Const.Length != 8 && Const.Length != 10 ) {
			ET.WriteParseError( ErrorIndex, "十六进制常量的数值符号数目要求为: 2, 4, 6, 8" );
			return 0;
		}
		Const = Const.Remove( 0, 2 );
		for( int i = 0; i < Const.Length; ++i ) {
			if( !isHexNumber( Const[ i ] ) ) {
				ET.WriteParseError( ErrorIndex, "十六进制常量中不能有非数值符号" );
				return 0;
			}
		}
		if( Const.Length > 8 ) {
			ET.WriteParseError( ErrorIndex, "十六进制常量的数值已经超出最大范围" );
			return 0;
		}
		long Number = 0;
		long Base = 1;
		for( int i = Const.Length - 1; i >= 0; --i ) {
			Number += HexToInteger( Const[ i ] ) * Base;
			Base *= 16;
		}
		return Number;
	}
	
	//转换二进制常量
	static long SwitchBin( string Const )
	{
		Const = String.Join( "", Const.Split( '_' ) );
		if( Const.Length != 10 && Const.Length != 18 && Const.Length != 26 && Const.Length != 34 ) {
			ET.WriteParseError( ErrorIndex, "二进制常量的数值符号数目要求为: 8, 16, 24, 32" );
			return 0;
		}
		Const = Const.Remove( 0, 2 );
		for( int i = 0; i < Const.Length; ++i ) {
			if( Const[ i ] != '0' && Const[ i ] != '1' ) {
				ET.WriteParseError( ErrorIndex, "二进制常量的数值符号只能为 0 或 1" );
				return 0;
			}
		}
		if( Const.Length > 32 ) {
			ET.WriteParseError( ErrorIndex, "二进制常量的数值已经超出最大范围" );
			return 0;
		}
		long Number = 0;
		long Base = 1;
		for( int i = Const.Length - 1; i >= 0; --i ) {
			Number += ( (int)Const[ i ] - 0x30 ) * Base;
			Base *= 2;
		}
		return Number;
	}
	
	//转换十进制常量
	static long SwitchDec( string Const, ref bool Fix )
	{
		if( Const.Length > 10 ) {
			ET.WriteParseError( ErrorIndex, "数值过大: " + Const );
			return 0;
		}
		int Dot = 0;
		
		if( Const.EndsWith( "f" ) ) {
			Const = Const.Remove( Const.Length - 1 );
			Dot = 1;
		}
		
		for( int i = 0; i < Const.Length; ++i ) {
			if( Const[ i ] == '.' ) {
				Dot++;
				continue;
			}
			if( !isDecNumber( Const[ i ] ) ) {
				ET.WriteParseError( ErrorIndex, "十进制常量中不能有非数字符号: " + Const );
				return 0;
			}
		}
		if( Dot > 1 ) {
			ET.WriteParseError( ErrorIndex, "小数点只能有一个: " + Const );
			return 0;
		}
		if( Dot != 0 ) {
			//return (long)((uint)(float.Parse( Const ) * 1000) | 0x40000000);
			Fix = true;
			return (long)(uint)(float.Parse( Const ) * FixScale);
		}
		return long.Parse( Const );
	}
	
	//获取一个有符号数的位宽度,以 1, 2, 3, ...等分隔
	static int GetSignedWidth( long n )
	{
		if( n <= 127 )					return 8;
		if( n <= 32767 )				return 16;
		//if( n <= 8388607 )				return 24;
		if( n <= 2147483647 )			return 32;
		
		//ET.WriteParseError( ErrorIndex, "常量值超出了有符号数变量类型的范围: " + n.ToString( "X" ) );
		return 64;
	}
	
	//获取一个无符号数的字节宽度,以 1, 2, 3, ...等分隔
	static int GetUnsignedWidth( long n )
	{
		//if( n <= 1 )					return 1;
		if( n <= 255 )					return 8;
		if( n <= 65535 )				return 16;
		//if( n <= 16777215 )				return 24;
		if( n <= 4294967295 )			return 32;
		
		//ET.WriteParseError( ErrorIndex, "常量值超出了无符号数变量类型的范围: " + n.ToString( "X" ) );
		return 64;
	}
	
	//判断是否为十进制数字
	static bool isDecNumber( char c )
	{
		if( c >= '0' && c <= '9' )
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	//判断是否为十六进制数字
	static bool isHexNumber( char c )
	{
		if( c >= '0' && c <= '9' ||
		    c >= 'a' && c <= 'f' ||
		    c >= 'A' && c <= 'F' )
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	//十六进制数字转化为0-15,非数值符号返回-1
	static int HexToInteger( char c )
	{
		if( isDecNumber( c ) )
		{
			return int.Parse( c.ToString() );
		}
		if( c >= 'A' && c <= 'F' )
		{
			return (int)c - 0x41 + 10;
		}
		if( c >= 'a' && c <= 'f' )
		{
			return (int)c - 0x61 + 10;
		}
		return -1;
	}
	
	static int ErrorIndex;
}
}

